const items = document.querySelectorAll('.list-item')
const playGroud = document.querySelector('.playground')
const list = document.querySelector('.list')

const title = document.querySelector('.title')


function createAnimation(scrollStart, scorllEnd, valueStart, valueEnd){
  return function(scroll){
    if(scroll<=scrollStart){
        return valueStart;
    }
    if(scroll>=scorllEnd){
        return valueEnd;
    }
    return valueStart + ((valueEnd-valueStart) * (scroll-scrollStart) ) / (scorllEnd - scrollStart)
  }
}


const animationMap = new Map()

function getDomAnimation(scrollStart, scrollEnd, dom){
    scrollStart = scrollStart + dom.dataset.order * 50
    // 渐显 
    const opacityAimation = createAnimation(scrollStart, scrollEnd, 0, 1)   
    // 渐出
    const opacityOutAimation = createAnimation(scrollEnd, scrollEnd + 300, 1, 0)
    //进入-放大
    const scaleAnimation = createAnimation(scrollStart, scrollEnd, 0.5, 1)
    //退出-放大
    const scaleOutAnimation = createAnimation(scrollEnd, scrollEnd + 400, 1, 2)
    //X轴 中心点至-水平位置
    const xAnimation = createAnimation(scrollStart, scrollEnd, list.clientWidth / 2 - dom.offsetLeft - dom.clientWidth / 2, 0)
    //Y轴 中心点至-垂直位置
    const yAnimation = createAnimation(scrollStart, scrollEnd, list.clientHeight / 2 - dom.offsetTop - dom.clientHeight / 2, 0)
    //Y轴 垂直初始位置至- 垂直退出
    const yOutAnimation = createAnimation(scrollEnd, scrollEnd+400, 0, -(list.clientHeight / 2 - dom.clientHeight / 2))

    // 透明函数
    const opacity = function(scroll){
        if(scroll>=scrollEnd && dom.dataset.name == 'title'){
            return opacityOutAimation(scroll);
        }
        return opacityAimation(scroll)
    }
    
    // 变换函数
    const transform = function(scroll){
        if(scroll>=scrollEnd && dom.dataset.name == 'title'){
            return `translate(${xAnimation(scroll)}px, ${yOutAnimation(scroll)}px) scale(${scaleOutAnimation(scroll)})`
        }
        return `translate(${xAnimation(scroll)}px, ${yAnimation(scroll)}px) scale(${scaleAnimation(scroll)})`
    }

    return {
        opacity,
        transform
    }
}



function updateMap(){
    animationMap.clear()
    const playGroudRect = playGroud.getBoundingClientRect()

    // 菜单模块
    const scrollStart = playGroudRect.top + window.scrollY; //当playGroudRect的top为0作为开始位置、
    const scrollEnd = playGroudRect.bottom + window.scrollY - window.innerHeight
    for(const item of items){
        animationMap.set(item, getDomAnimation(scrollStart, scrollEnd, item))
    }

    // 标题logo模块
    const title_scrollStart = (playGroudRect.top + window.scrollY)/4; 
    const title_scrollEnd = playGroudRect.top + window.scrollY
    animationMap.set(title, getDomAnimation(title_scrollStart, title_scrollEnd, title))
 
}

updateMap()

function updateStyles(){
    const scroll = window.scrollY
    for(let [dom, value] of animationMap){
         for(const cssprop in value){
            dom.style[cssprop] = value[cssprop](scroll)
         }
    }
}
updateStyles()

window.addEventListener('scroll', updateStyles)


// 盒子随机颜色
document.addEventListener("DOMContentLoaded", function () {
    // 定义随机颜色数组
    const colors = [
      "#2b90fb",
      "#39b84f",
      "#cf9327",
      "#f88d21",
      "#cd5e3a",
      "#2b90fb",
      "#39b84f"
    ];
  
    // 从颜色数组中随机选择一个颜色
    function getRandomColor() {
      return colors[Math.floor(Math.random() * colors.length)];
    }
  
    // 获取所有带有“random-bg-color”类的元素
    const elements = document.querySelectorAll(".random-bg-color");
  
    // 为每个元素设置随机背景颜色
    elements.forEach(function (element) {
      element.style.backgroundColor = getRandomColor();
    });
  });


//   1111
//   点击出现照片
const downloadButton = document.getElementById("downloadButton");
const popup = document.querySelector(".popup");
const popupImage = popup.querySelector(".popup_image");

// 监听下载按钮的点击事件
downloadButton.addEventListener("click", () => {
  // 显示弹框
  popup.style.display = "flex";
  downloadButton.style.cursor = "pointer";
  // 设置弹框中的图片
  popupImage.src = "./img/dev.png";
});

// 监听弹框的点击事件
popup.addEventListener("click", () => {
  // 隐藏弹框
  popup.style.display = "none";
  downloadButton.style.cursor = "default";
});
downloadButton.addEventListener("mouseenter", () => {
    // 鼠标进入时将光标样式更改为 "pointer"
    downloadButton.style.cursor = "pointer";
  });

//   轮播图



// 粒子特效
class ShaderProgram {

  constructor(holder, options = {}) {

      options = Object.assign({
          antialias: false,
          depthTest: false,
          mousemove: false,
          autosize: true,
          side: 'front',
          vertex: `
        precision highp float;

        attribute vec4 a_position;
        attribute vec4 a_color;

        uniform float u_time;
        uniform vec2 u_resolution;
        uniform vec2 u_mousemove;
        uniform mat4 u_projection;

        varying vec4 v_color;

        void main() {

          gl_Position = u_projection * a_position;
          gl_PointSize = (10.0 / gl_Position.w) * 100.0;

          v_color = a_color;

        }`,
          fragment: `
        precision highp float;

        uniform sampler2D u_texture;
        uniform int u_hasTexture;

        varying vec4 v_color;

        void main() {

          if ( u_hasTexture == 1 ) {

            gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);

          } else {

            gl_FragColor = v_color;

          }

        }`,
          uniforms: {},
          buffers: {},
          camera: {},
          texture: null,
          onUpdate: (() => {}),
          onResize: (() => {}),
      }, options)

      const uniforms = Object.assign({
          time: { type: 'float', value: 0 },
          hasTexture: { type: 'int', value: 0 },
          resolution: { type: 'vec2', value: [0, 0] },
          mousemove: { type: 'vec2', value: [0, 0] },
          projection: { type: 'mat4', value: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] },
      }, options.uniforms)

      const buffers = Object.assign({
          position: { size: 3, data: [] },
          color: { size: 4, data: [] },
      }, options.buffers)

      const camera = Object.assign({
          fov: 60,
          near: 1,
          far: 10000,
          aspect: 1,
          z: 100,
          perspective: true,
      }, options.camera)

      const canvas = document.createElement('canvas')
      const gl = canvas.getContext('webgl', { antialias: options.antialias })

      if (!gl) return false

      this.count = 0
      this.gl = gl
      this.canvas = canvas
      this.camera = camera
      this.holder = holder
      this.onUpdate = options.onUpdate
      this.onResize = options.onResize
      this.data = {}

      holder.appendChild(canvas)

      this.createProgram(options.vertex, options.fragment)

      this.createBuffers(buffers)
      this.createUniforms(uniforms)

      this.updateBuffers()
      this.updateUniforms()

      this.createTexture(options.texture)

      gl.enable(gl.BLEND)
      gl.enable(gl.CULL_FACE)
      gl.blendFunc(gl.SRC_ALPHA, gl.ONE)
      gl[options.depthTest ? 'enable' : 'disable'](gl.DEPTH_TEST)

      if (options.autosize)
          window.addEventListener('resize', e => this.resize(e), false)
      if (options.mousemove)
          window.addEventListener('mousemove', e => this.mousemove(e), false)

      this.resize()

      this.update = this.update.bind(this)
      this.time = { start: performance.now(), old: performance.now() }
      this.update()

  }

  mousemove(e) {

      let x = e.pageX / this.width * 2 - 1
      let y = e.pageY / this.height * 2 - 1

      this.uniforms.mousemove = [x, y]

  }

  resize(e) {

      const holder = this.holder
      const canvas = this.canvas
      const gl = this.gl

      const width = this.width = holder.offsetWidth
      const height = this.height = holder.offsetHeight
      const aspect = this.aspect = width / height
      const dpi = this.dpi = devicePixelRatio

      canvas.width = width * dpi
      canvas.height = height * dpi
      canvas.style.width = width + 'px'
      canvas.style.height = height + 'px'

      gl.viewport(0, 0, width * dpi, height * dpi)
      gl.clearColor(0, 0, 0, 0)

      this.uniforms.resolution = [width, height]
      this.uniforms.projection = this.setProjection(aspect)

      this.onResize(width, height, dpi)

  }

  setProjection(aspect) {

      const camera = this.camera

      if (camera.perspective) {

          camera.aspect = aspect

          const fovRad = camera.fov * (Math.PI / 180)
          const f = Math.tan(Math.PI * 0.5 - 0.5 * fovRad)
          const rangeInv = 1.0 / (camera.near - camera.far)

          const matrix = [
              f / camera.aspect, 0, 0, 0,
              0, f, 0, 0,
              0, 0, (camera.near + camera.far) * rangeInv, -1,
              0, 0, camera.near * camera.far * rangeInv * 2, 0
          ]

          matrix[14] += camera.z
          matrix[15] += camera.z

          return matrix

      } else {

          return [
              2 / this.width, 0, 0, 0,
              0, -2 / this.height, 0, 0,
              0, 0, 1, 0, -1, 1, 0, 1,
          ]

      }

  }

  createShader(type, source) {

      const gl = this.gl
      const shader = gl.createShader(type)

      gl.shaderSource(shader, source)
      gl.compileShader(shader)

      if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {

          return shader

      } else {

          console.log(gl.getShaderInfoLog(shader))
          gl.deleteShader(shader)

      }

  }

  createProgram(vertex, fragment) {

      const gl = this.gl

      const vertexShader = this.createShader(gl.VERTEX_SHADER, vertex)
      const fragmentShader = this.createShader(gl.FRAGMENT_SHADER, fragment)

      const program = gl.createProgram()

      gl.attachShader(program, vertexShader)
      gl.attachShader(program, fragmentShader)
      gl.linkProgram(program)

      if (gl.getProgramParameter(program, gl.LINK_STATUS)) {

          gl.useProgram(program)
          this.program = program

      } else {

          console.log(gl.getProgramInfoLog(program))
          gl.deleteProgram(program)

      }

  }

  createUniforms(data) {

      const gl = this.gl
      const uniforms = this.data.uniforms = data
      const values = this.uniforms = {}

      Object.keys(uniforms).forEach(name => {

          const uniform = uniforms[name]

          uniform.location = gl.getUniformLocation(this.program, 'u_' + name)

          Object.defineProperty(values, name, {
              set: value => {

                  uniforms[name].value = value
                  this.setUniform(name, value)

              },
              get: () => uniforms[name].value
          })

      })

  }

  setUniform(name, value) {

      const gl = this.gl
      const uniform = this.data.uniforms[name]

      uniform.value = value

      switch (uniform.type) {
          case 'int':
              {
                  gl.uniform1i(uniform.location, value)
                  break
              }
          case 'float':
              {
                  gl.uniform1f(uniform.location, value)
                  break
              }
          case 'vec2':
              {
                  gl.uniform2f(uniform.location, ...value)
                  break
              }
          case 'vec3':
              {
                  gl.uniform3f(uniform.location, ...value)
                  break
              }
          case 'vec4':
              {
                  gl.uniform4f(uniform.location, ...value)
                  break
              }
          case 'mat2':
              {
                  gl.uniformMatrix2fv(uniform.location, false, value)
                  break
              }
          case 'mat3':
              {
                  gl.uniformMatrix3fv(uniform.location, false, value)
                  break
              }
          case 'mat4':
              {
                  gl.uniformMatrix4fv(uniform.location, false, value)
                  break
              }
      }

      // ivec2       : uniform2i,
      // ivec3       : uniform3i,
      // ivec4       : uniform4i,
      // sampler2D   : uniform1i,
      // samplerCube : uniform1i,
      // bool        : uniform1i,
      // bvec2       : uniform2i,
      // bvec3       : uniform3i,
      // bvec4       : uniform4i,

  }

  updateUniforms() {

      const gl = this.gl
      const uniforms = this.data.uniforms

      Object.keys(uniforms).forEach(name => {

          const uniform = uniforms[name]

          this.uniforms[name] = uniform.value

      })

  }

  createBuffers(data) {

      const gl = this.gl
      const buffers = this.data.buffers = data
      const values = this.buffers = {}

      Object.keys(buffers).forEach(name => {

          const buffer = buffers[name]

          buffer.buffer = this.createBuffer('a_' + name, buffer.size)

          Object.defineProperty(values, name, {
              set: data => {

                  buffers[name].data = data
                  this.setBuffer(name, data)

                  if (name == 'position')
                      this.count = buffers.position.data.length / 3

              },
              get: () => buffers[name].data
          })

      })

  }

  createBuffer(name, size) {

      const gl = this.gl
      const program = this.program

      const index = gl.getAttribLocation(program, name)
      const buffer = gl.createBuffer()

      gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
      gl.enableVertexAttribArray(index)
      gl.vertexAttribPointer(index, size, gl.FLOAT, false, 0, 0)

      return buffer

  }

  setBuffer(name, data) {

      const gl = this.gl
      const buffers = this.data.buffers

      if (name == null && !gl.bindBuffer(gl.ARRAY_BUFFER, null)) return

      gl.bindBuffer(gl.ARRAY_BUFFER, buffers[name].buffer)
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW)

  }

  updateBuffers() {

      const gl = this.gl
      const buffers = this.buffers

      Object.keys(buffers).forEach(name =>
          buffers[name] = buffer.data
      )

      this.setBuffer(null)

  }

  createTexture(src) {

      const gl = this.gl
      const texture = gl.createTexture()

      gl.bindTexture(gl.TEXTURE_2D, texture)
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]))

      this.texture = texture

      if (src) {

          this.uniforms.hasTexture = 1
          this.loadTexture(src)

      }

  }

  loadTexture(src) {

      const gl = this.gl
      const texture = this.texture

      const textureImage = new Image()

      textureImage.onload = () => {

          gl.bindTexture(gl.TEXTURE_2D, texture)

          gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImage)

          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
          gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

          // gl.generateMipmap( gl.TEXTURE_2D )

      }

      textureImage.src = src

  }

  update() {

      const gl = this.gl

      const now = performance.now()
      const elapsed = (now - this.time.start) / 5000
      const delta = now - this.time.old
      this.time.old = now

      this.uniforms.time = elapsed

      if (this.count > 0) {
          gl.clear(gl.COLORBUFFERBIT)
          gl.drawArrays(gl.POINTS, 0, this.count)
      }

      this.onUpdate(delta)

      requestAnimationFrame(this.update)

  }

}

const pointSize = 2.5

const waves = new ShaderProgram(document.querySelector('.waves'), {
  texture: '',
  uniforms: {
      size: { type: 'float', value: pointSize },
      field: { type: 'vec3', value: [0, 0, 0] },
      speed: { type: 'float', value: 5 },
  },
  vertex: `
    #define M_PI 3.1415926535897932384626433832795

    precision highp float;

    attribute vec4 a_position;
    attribute vec4 a_color;

    uniform float u_time;
    uniform float u_size;
    uniform float u_speed;
    uniform vec3 u_field;
    uniform mat4 u_projection;

    varying vec4 v_color;

    void main() {

      vec3 pos = a_position.xyz;

      pos.y += (
        cos(pos.x / u_field.x * M_PI * 8.0 + u_time * u_speed) +
        sin(pos.z / u_field.z * M_PI * 8.0 + u_time * u_speed)
      ) * u_field.y ;

      gl_Position = u_projection * vec4( pos.xyz, a_position.w );
      gl_PointSize = ( u_size / gl_Position.w ) * 100.0;

      v_color = a_color;

    }`,
  fragment: `
    precision highp float;

    uniform sampler2D u_texture;

    varying vec4 v_color;

    void main() {

      gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);

    }`,
  onResize(w, h, dpi) {

      const position = [],
          color = []

      const width = 400 * (w / h)
      const depth = 400
      const height = 3
      const distance = 5

      for (let x = 0; x < width; x += distance) {
          for (let z = 0; z < depth; z += distance) {

              position.push(-width / 2 + x, -30, -depth / 2 + z)
              color.push(0, 1 - (x / width) * 1, 0.5 + x / width * 0.5, z / depth)

          }
      }

      this.uniforms.field = [width, height, depth]

      this.buffers.position = position
      this.buffers.color = color

      this.uniforms.size = (h / 400) * pointSize * dpi

  },
  
}
)